package org.dromara.northstar.gateway.okx;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.google.gson.Gson;
import com.okex.open.api.config.APIConfiguration;
import com.okex.open.api.service.account.impl.AccountAPIServiceImpl;
import com.okex.open.api.service.publicData.impl.PublicDataAPIServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.dromara.northstar.common.model.core.ContractDefinition;
import org.dromara.northstar.common.model.core.TimeSlot;
import org.dromara.northstar.common.model.core.TradeTimeDefinition;
import org.dromara.northstar.common.utils.DateTimeUtils;
import org.dromara.northstar.gateway.IMarketCenter;
import org.springframework.stereotype.Component;
import xyz.redtorch.pb.CoreEnum;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;
import java.util.stream.Collectors;


@Slf4j
@Component
public class OkxContractProvider {
    private OkxDataServiceManager dataMgr;

    private IMarketCenter mktCenter;

    private OkxGatewaySettings okxGatewaySettings;
    private TimeSlot allDay = TimeSlot.builder().start(DateTimeUtils.fromCacheTime(0, 0)).end(DateTimeUtils.fromCacheTime(0, 0)).build();


    public OkxContractProvider(OkxGatewaySettings settings, IMarketCenter mktCenter, OkxDataServiceManager dataMgr) {
        this.okxGatewaySettings = settings;
        this.mktCenter = mktCenter;
        this.dataMgr = dataMgr;
    }

    public void loadContractOptions() {
        APIConfiguration config = new APIConfiguration();
        config.setDomain("https://www.okx.com/");
        //secretKey,api注册成功后页面上有
        config.setApiKey(okxGatewaySettings.getApiKey());
        config.setSecretKey(okxGatewaySettings.getSecretKey());
        //Passphrase忘记后无法找回
        config.setPassphrase(okxGatewaySettings.getPassphrase());
        //请求模拟盘的接口需要传入1，否则传入0
        config.setxSimulatedTrading(okxGatewaySettings.getAccountType());
        //加载OKX合约定义
        mktCenter.addDefinitions(getRegisteredContract(config));

        //交易规则和交易对
        AccountAPIServiceImpl accountAPIService = new AccountAPIServiceImpl(config);
        PublicDataAPIServiceImpl publicDataAPIService = new PublicDataAPIServiceImpl(config);

        JSONObject result = publicDataAPIService.getInstruments("SWAP", "", "", "");
        JSONArray data = result.getJSONArray("data");
        // 使用 Gson 将 LinkedTreeMap 转换为 JSON 字符串，然后转换为 JSONObject
        Gson gson = new Gson();
        List<JSONObject> list = data.stream()
                .map(item -> JSONObject.parseObject(gson.toJson(item)))
                .filter(x -> CoreEnum.CurrencyEnum.USDT.name().equals(x.getString("settleCcy")))
                .toList();

        List<String> instIdList = list.stream().map(x -> x.getString("instId")).toList();
        //获取杠杆倍数
        List<List<String>> split = CollUtil.split(instIdList, 20);

        Map<String, JSONObject> longPositionMap = new HashMap<>();
        Map<String, JSONObject> shortPositionMap = new HashMap<>();
        for (List<String> strings : split) {
            // 拼接成半角逗号分隔的字符串
            String instIds = String.join(",", strings);
            // 调用API方法并传递参数
            JSONObject leverage = accountAPIService.getLeverage(instIds, "cross");
            JSONArray leverageList = leverage.getJSONArray("data");

            longPositionMap.putAll(leverageList.stream()
                    .map(item -> JSONObject.parseObject(gson.toJson(item)))
                    .filter(item -> "long".equals(item.getString("posSide")))
                    .collect(Collectors.toMap(x -> x.getString("instId"), x -> x, (oldValue, newValue) -> oldValue)));

            shortPositionMap.putAll(leverageList.stream()
                    .map(item -> JSONObject.parseObject(gson.toJson(item)))
                    .filter(item -> "short".equals(item.getString("posSide")))
                    .collect(Collectors.toMap(x -> x.getString("instId"), x -> x, (oldValue, newValue) -> oldValue)));
        }
        for (JSONObject obj : list) {
            JSONObject longSymbol = longPositionMap.get(obj.getString("instId"));
            JSONObject shortSymbol = shortPositionMap.get(obj.getString("instId"));

            if (ObjectUtil.isEmpty(longSymbol) || ObjectUtil.isEmpty(shortSymbol)){
                continue;
            }
            //计算多头空头保证金率
            obj.put("longMarginRatio", 1 / longSymbol.getDoubleValue("lever"));
            obj.put("shortMarginRatio", 1 / shortSymbol.getDoubleValue("lever"));

            //注册合约
            mktCenter.addInstrument(new OkxContract(obj, dataMgr));
        }

        //加载现货
        result = publicDataAPIService.getInstruments("SPOT", "", "", "");
        data = result.getJSONArray("data");
        list = data.stream()
                .map(item -> JSONObject.parseObject(gson.toJson(item)))
                .filter(x -> CoreEnum.CurrencyEnum.USDT.name().equals(x.getString("quoteCcy")))
                .toList();
        for (JSONObject obj : list) {
            //注册现货
            mktCenter.addInstrument(new OkxContract(obj, dataMgr));
        }
    }

    public List<ContractDefinition> getRegisteredContract(APIConfiguration config) {
        List<ContractDefinition> contractDefs = new ArrayList<>();

        AccountAPIServiceImpl accountAPIService = new AccountAPIServiceImpl(config);
        JSONObject swapResult = accountAPIService.getInstruments("SWAP", "", "", "");
        JSONObject spotResult = accountAPIService.getInstruments("SPOT", "", "", "");
        JSONArray swapData = swapResult.getJSONArray("data");
        JSONArray spotData = spotResult.getJSONArray("data");

        swapData.addAll(spotData);
        for (int i = 0; i < swapData.size(); i++) {
            JSONObject jsonObject = swapData.getJSONObject(i);
            if (CoreEnum.ProductClassEnum.SPOT.name().equals(jsonObject.getString("instType"))) {
                //过滤掉非USDT的币种
                if (CoreEnum.CurrencyEnum.USDT.name().equals(jsonObject.getString("quoteCcy"))) {
                    getContractDefinition(contractDefs, jsonObject);
                }
            } else if (CoreEnum.ProductClassEnum.SWAP.name().equals(jsonObject.getString("instType"))) {
                //过滤掉非USDT的币种
                if (CoreEnum.CurrencyEnum.USDT.name().equals(jsonObject.getString("settleCcy"))) {
                    getContractDefinition(contractDefs, jsonObject);
                }
            }

        }
        return contractDefs;
    }

    private void getContractDefinition(List<ContractDefinition> contractDefs, JSONObject jsonObject) {
        OkxContract contract = new OkxContract(jsonObject, dataMgr);
        ContractDefinition cnFtTt1 = ContractDefinition.builder()
                .name(contract.name())
                .exchange(contract.exchange())
                .productClass(contract.productClass())
                .symbolPattern(Pattern.compile(contract.name() + "@[A-Z]+@[A-Z]+@[A-Z]+$"))
                .commissionRate(3 / 10000D).dataSource(dataMgr)
                .tradeTimeDef(TradeTimeDefinition.builder().timeSlots(List.of(allDay)).build())
                .build();
        contractDefs.add(cnFtTt1);
    }
}
